package service

import (
	"context"
	"errors"
	"gorm.io/gorm"
	"shop-bean/model"
	"shop-common/library/variables"
	"shop-common/utils/queryWrapper"
	"shop-service/cache"
	"shop-service/repository"
)

type IAreaService interface {
	Create(ctx context.Context, area *model.Area) error
	Delete(ctx context.Context, id uint) error
	Updates(ctx context.Context, id uint, columns map[string]interface{}) error
	Find(ctx context.Context, pair *queryWrapper.WherePair) ([]*model.Area, error)
}

type AreaService struct {
	db          *gorm.DB
	repository  repository.IAreaRepository
	redisClient cache.IRedisAreaCache
}

func NewAreaService(repository repository.IAreaRepository) IAreaService {
	return &AreaService{variables.GormDB(), repository, cache.NewRedisAreaCache()}
}

func (s *AreaService) Create(ctx context.Context, area *model.Area) error {
	err := s.repository.Create(s.db, area)
	if err != nil {
		variables.Logger.Errorf(ctx, "create area failed: %v", err)
		return err
	}

	_ = s.redisClient.Remove(area.ParentId)
	return nil
}

func (s *AreaService) Delete(ctx context.Context, id uint) error {
	err := s.repository.Delete(s.db, id)
	if err != nil {
		variables.Logger.Errorf(ctx, "delete area failed: %v, id %d", err, id)
		return err
	}

	_ = s.redisClient.Remove(id)
	return nil
}

func (s *AreaService) Updates(ctx context.Context, id uint, columns map[string]interface{}) error {
	err := s.repository.Updates(s.db, id, columns)
	if err != nil {
		variables.Logger.Errorf(ctx, "updates area failed: err %v, id %d, columns: %+v", err, id, columns)
		return err
	}
	_ = s.redisClient.Remove(id)
	return nil
}

func (s *AreaService) Find(ctx context.Context, pair *queryWrapper.WherePair) ([]*model.Area, error) {
	var pid uint
	if pair != nil && len(pair.Args) == 1 {
		pid = pair.Args[0].(uint)
	}

	cacheData, err := s.redisClient.GetCache(pid)
	if len(cacheData) > 0 && err == nil {

		return cacheData, nil
	}

	list, err := s.repository.Find(s.db, pair)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		variables.Logger.Errorf(ctx, "find area failed: err %v, pair %+v", err, pair)
		return nil, err
	}

	if err := s.redisClient.PutCache(pid, list); err != nil {
		variables.Logger.Errorf(ctx, "cache set area failed: err %v", err)
	}

	return list, nil
}

//func filterCacheAreas(cacheData []*model.Area, pid uint) (list []*model.Area) {
//	for _, item := range cacheData {
//		if item.ParentId == pid {
//			list = append(list, item)
//		}
//	}
//
//	return list
//}
